UNPKG

marko

Version:

UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.

236 lines (202 loc) • 6.76 kB
"use strict";exports.__esModule = true;exports.default = _default;var _compiler = require("@marko/compiler"); var _babelUtils = require("@marko/compiler/babel-utils"); var _path = require("path"); var _selfClosingTags = _interopRequireDefault(require("self-closing-tags")); var _htmlOutWrite = _interopRequireDefault(require("../../util/html-out-write")); var _keyManager = require("../../util/key-manager"); var _withPreviousLocation = _interopRequireDefault(require("../../util/with-previous-location")); var _attributes = _interopRequireDefault(require("./attributes"));function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };} const EMPTY_OBJECT = {}; /** * Translates the html streaming version of a standard html element. */ function _default(path, isNullable) { const { hub: { file }, node } = path; const { key, name, body: { body }, handlers } = node; const tagProperties = path.node.extra && path.node.extra.properties || []; const tagDef = (0, _babelUtils.getTagDef)(path); const meta = file.metadata.marko; if (tagDef) { const { parseOptions = EMPTY_OBJECT } = tagDef; if (parseOptions.import) { // TODO: the taglib should be updated to support this as a top level option. file.metadata.marko.deps.push((0, _path.resolve)(tagDef.dir, parseOptions.import)); } } if (handlers) { Object.entries(handlers).forEach( ([eventName, { arguments: args, once }]) => { const delegateArgs = [_compiler.types.stringLiteral(eventName), args[0]]; // TODO: look into only sending this if once is true. delegateArgs.push(_compiler.types.booleanLiteral(once)); if (args.length > 1) { delegateArgs.push(_compiler.types.arrayExpression(args.slice(1))); } // TODO: why do we output eventName twice. tagProperties.push( _compiler.types.objectProperty( _compiler.types.stringLiteral(`on${eventName}`), _compiler.types.callExpression( _compiler.types.memberExpression( file._componentDefIdentifier, _compiler.types.identifier("d") ), delegateArgs ) ) ); } ); } const isHTML = file.markoOpts.output === "html"; let dataMarko = _compiler.types.stringLiteral(""); if (node.preserveAttrs) { tagProperties.push( _compiler.types.objectProperty( _compiler.types.identifier("pa"), _compiler.types.objectExpression( node.preserveAttrs.map((name) => _compiler.types.objectProperty( _compiler.types.isValidIdentifier(name) ? _compiler.types.identifier(name) : _compiler.types.stringLiteral(name), _compiler.types.numericLiteral(1) ) ) ) ) ); } if (isHTML) { if ( !meta.hasStatefulTagParams && !meta.hasFunctionEventHandlers && ( meta.hasComponentBrowser || !meta.hasComponent) || isPreserved(path)) { const dataMarkoArgs = [_compiler.types.identifier("out"), file._componentDefIdentifier]; if (tagProperties.length) { // TODO we should pre evaluate this if it is static. dataMarkoArgs.push(_compiler.types.objectExpression(tagProperties)); } if ((0, _keyManager.hasUserKey)(path) || key && node.isPreserved) { if (dataMarkoArgs.length === 2) { dataMarkoArgs.push(_compiler.types.numericLiteral(0)); } dataMarkoArgs.push(key); } if (dataMarkoArgs.length > 2) { dataMarko = _compiler.types.callExpression( (0, _babelUtils.importDefault)( file, "marko/src/runtime/html/helpers/data-marko.js", "marko_props" ), dataMarkoArgs ); } } } const translatedAttrs = (0, _attributes.default)(path, path.get("attributes")); let isSelfClosing = false; let openTagEnding = ">"; if (_compiler.types.isStringLiteral(name)) { if ( tagDef && tagDef.htmlType && ( tagDef.htmlType === "svg" || tagDef.htmlType === "math")) { if (!body.length) { isSelfClosing = true; openTagEnding = " />"; } } else if (_selfClosingTags.default.voidElements.indexOf(name.value) !== -1) { isSelfClosing = true; } } const isEmpty = isSelfClosing || !body.length; let writeStartNode = (0, _babelUtils.normalizeTemplateString)`<${name}${dataMarko}${translatedAttrs}${openTagEnding}`; writeStartNode = (0, _withPreviousLocation.default)( isEmpty && !isSelfClosing ? (0, _htmlOutWrite.default)`${writeStartNode}</${name}>` : (0, _htmlOutWrite.default)`${writeStartNode}`, name ); if (isNullable) { writeStartNode = _compiler.types.ifStatement(name, writeStartNode); if (!isEmpty) { writeStartNode.alternate = _compiler.types.expressionStatement( _compiler.types.callExpression( _compiler.types.memberExpression(_compiler.types.identifier("out"), _compiler.types.identifier("bf")), [ (0, _babelUtils.normalizeTemplateString)`f_${key}`, file._componentInstanceIdentifier, _compiler.types.numericLiteral(1)] ) ); } } if (isEmpty) { path.replaceWith(writeStartNode); return; } let needsBlock; let needsIIFE; for (const childNode of body) { if (_compiler.types.isVariableDeclaration(childNode)) { if (childNode.kind === "const" || childNode.kind === "let") { needsBlock = true; } else { needsIIFE = true; } break; } } let writeEndNode = (0, _htmlOutWrite.default)`</${name}>`; if (isNullable) { writeEndNode = _compiler.types.ifStatement( name, writeEndNode, _compiler.types.expressionStatement( _compiler.types.callExpression( _compiler.types.memberExpression(_compiler.types.identifier("out"), _compiler.types.identifier("ef")), [] ) ) ); } path.replaceWithMultiple( [writeStartNode]. concat( needsIIFE ? _compiler.types.expressionStatement( _compiler.types.callExpression( _compiler.types.arrowFunctionExpression([], _compiler.types.blockStatement(body)), [] ) ) : needsBlock ? _compiler.types.blockStatement(body) : body ). concat(writeEndNode) ); } function isPreserved(path) { let parentTag = path; do { parentTag = parentTag.parentPath.parentPath; if (parentTag.get("isPreserved").node === true) { return true; } } while (_compiler.types.isMarkoTag(parentTag)); return false; }